﻿/*
COPYRIGHT (C) 2009 EPISERVER AB

THIS FILE IS PART OF REMOTE PAGE PROVIDER FOR EPISERVER CMS.
REMOTE PAGE PROVIDER FOR EPISERVER CMS IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

REMOTE PAGE PROVIDER FOR EPISERVER CMS IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH REMOTE PAGE PROVIDER FOR EPISERVER CMS]. IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Hosting;
using System.IO;
using EPiServer.Web.Hosting;
using EPiServer.Security;
using System.Collections;
using EPiServer.Core;

namespace EPiServer.Labs.RemoteProvider
{
    public class RemoteUnifiedDirectory:  UnifiedDirectory, IPageDirectory
    {

        /// <summary>
        /// The File Server provider
        /// </summary>
        IRemoteProvider             _remoteFileServer;
        RemoteDirectoryInfo         _remoteDirInfo;
        RemoteUnifiedDirectory      _parent;

        /// <summary>
        /// Initializes a new instance of the <see cref="RemoteUnifiedDirectory"/> class.
        /// </summary>
        /// <param name="remoteFileServer">The remote file server.</param>
        /// <param name="provider">The provider.</param>
        /// <param name="remoteDirInfo">The remote dir info.</param>
        public RemoteUnifiedDirectory(
                        IRemoteProvider remoteFileServer, 
                        VirtualPathUnifiedProvider provider, 
                        RemoteDirectoryInfo remoteDirInfo): base(provider, remoteDirInfo.VirtualPath, provider.ConfigFileSummaryFullPath, remoteDirInfo.BypassAccessCheck)
        {
            _remoteFileServer = remoteFileServer;
            _remoteDirInfo = remoteDirInfo;
        }


        #region UnifiedDirectoy overrides
        /// <summary>
        /// Gets the parent.
        /// </summary>
        /// <value>The parent.</value>
        public override UnifiedDirectory Parent
        {
            get
            {
                if (_remoteDirInfo.Parent == null)
                {
                    return null;
                }
                if (_parent== null)
                {
                    _parent = new RemoteUnifiedDirectory(_remoteFileServer, Provider, _remoteDirInfo.Parent);
                }
                return _parent;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is first level.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is first level; otherwise, <c>false</c>.
        /// </value>
        public override bool IsFirstLevel
        {
            get
            {
                return _remoteDirInfo.IsFirstLevel;
            }
        }

        /// <summary>
        /// Gets the children.
        /// </summary>
        /// <value>The children.</value>
        public override IEnumerable Children
        {
            get
            {
                RemoteDirectoryInfo[] directories = _remoteFileServer.Directories(LocalVirtualPathToRemoteVirtualPath(_remoteDirInfo.VirtualPath));
                RemoteFileInfo[] files = _remoteFileServer.Files(LocalVirtualPathToRemoteVirtualPath(_remoteDirInfo.VirtualPath));
                
                // Get the two separate list.
                List<object> children = new List<object>(directories.Length + files.Length);
                foreach (RemoteDirectoryInfo remoteDirInfo in directories)
                {
                    remoteDirInfo.VirtualPath = RemoteVirtualPathToLocalVirtualPath(remoteDirInfo.VirtualPath);
                    //remoteDirInfo.Parent.LocalVirtualPath = RemoteVirtualPathToLocalVirtualPath(remoteDirInfo.Parent.RemoteVirtualPath);
                    children.Add(new RemoteUnifiedDirectory(_remoteFileServer, Provider, remoteDirInfo));
                }

                foreach (RemoteFileInfo remoteFileInfo in files)
                {
                    remoteFileInfo.VirtualPath= RemoteVirtualPathToLocalVirtualPath(remoteFileInfo.VirtualPath);
                    children.Add(new RemoteUnifiedFile(_remoteFileServer, this, Provider, remoteFileInfo));
                }
                return children;
            }
        }

        /// <summary>
        /// Gets the directories.
        /// </summary>
        /// <value>The directories.</value>
        public override IEnumerable Directories
        {
            get
            {
                if (IsFirstLevel)
                {
                    return ((RemoteVirtualPathProvider)Provider).Directories.ToArray();
                }

                
                RemoteDirectoryInfo[] directories = _remoteFileServer.Directories(LocalVirtualPathToRemoteVirtualPath(_remoteDirInfo.VirtualPath));
                List<object> dirs = new List<object>(directories.Length);
                foreach (RemoteDirectoryInfo remoteDirInfo in directories)
                {
                    remoteDirInfo.VirtualPath = RemoteVirtualPathToLocalVirtualPath(remoteDirInfo.VirtualPath);
                    remoteDirInfo.IsFirstLevel = false;
                    //remoteDirInfo.Parent.LocalVirtualPath = RemoteVirtualPathToLocalVirtualPath(remoteDirInfo.Parent.RemoteVirtualPath);
                    dirs.Add(new RemoteUnifiedDirectory(
                            _remoteFileServer, 
                            Provider, 
                            remoteDirInfo));
                }
                return dirs;
            }
        }

        /// <summary>
        /// Gets the files.
        /// </summary>
        /// <value>The files.</value>
        public override IEnumerable Files
        {
            get
            {
                if (_remoteDirInfo.Parent == null)
                {
                    return new List<object>();
                }

                RemoteFileInfo[] filesInfo = _remoteFileServer.Files(LocalVirtualPathToRemoteVirtualPath(_remoteDirInfo.VirtualPath));
                List<object> files = new List<object>(filesInfo.Length);
                foreach (RemoteFileInfo remoteFileInfo in filesInfo)
                {
                    remoteFileInfo.VirtualPath = RemoteVirtualPathToLocalVirtualPath(remoteFileInfo.VirtualPath);
                    remoteFileInfo.Parent = _remoteDirInfo;
                    files.Add(new RemoteUnifiedFile(
                            _remoteFileServer, 
                            this, 
                            Provider,
                            remoteFileInfo));
                }
                return files;
            
            }
        }

        /// <summary>
        /// Queries the access.
        /// </summary>
        /// <returns></returns>
        public override AccessLevel QueryAccess()
        {
            return _remoteDirInfo.AccessLevel;
        }

        /// <summary>
        /// Gets the directories.
        /// </summary>
        /// <returns></returns>
        public override UnifiedDirectory[] GetDirectories()
        {
            List<UnifiedDirectory> dirs = new List<UnifiedDirectory>();
            foreach (RemoteUnifiedDirectory dir in Directories)
            {
                dirs.Add(dir);
            }

            return dirs.ToArray();
        }

        /// <summary>
        /// Gets the files.
        /// </summary>
        /// <returns></returns>
        public override UnifiedFile[] GetFiles()
        {
            List<UnifiedFile> files = new List<UnifiedFile>();
            foreach (RemoteUnifiedFile file in Files)
            {
                files.Add(file);
            }
            return files.ToArray();
        }

        /// <summary>
        /// Deletes this instance.
        /// </summary>
        public override void Delete()
        {
            throw new Exception("The Delete Not Supported by this provider");
        }

        /// <summary>
        /// Creates the file.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public override UnifiedFile CreateFile(string name, Guid id)
        {
            throw new Exception("The CreateFile Not Supported by this provider");
        }

        /// <summary>
        /// Creates the file.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public override UnifiedFile CreateFile(string name)
        {
            return CreateFile(name, Guid.Empty);
        }

        /// <summary>
        /// Creates the subdirectory.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public override UnifiedDirectory CreateSubdirectory(string name)
        {
            throw new Exception("The CreateSubdirectory Not Supported by this provider");
        }

        /// <summary>
        /// Copies to.
        /// </summary>
        /// <param name="destVirtualPath">The dest virtual path.</param>
        public override void CopyTo(string destVirtualPath)
        {
            throw new Exception("The CopyTo Not Supported by this provider");
        }

        /// <summary>
        /// Moves to.
        /// </summary>
        /// <param name="destVirtualPath">The dest virtual path.</param>
        public override void MoveTo(string destVirtualPath)
        {
            throw new Exception("The MoveTo Not Supported by this provider");
        }
        #endregion


        #region IPageDirectory Members

        public UnifiedDirectory CreateSubdirectory(string path, PageData accessValidatingPage)
        {
            throw new Exception("The CreateSubdirectory Not Supported by this provider");
        }

        #endregion


        #region Helper Method
        /// <summary>
        /// Remotes the virtual path to local virtual path.
        /// </summary>
        /// <param name="remoteVirtualPath">The remote virtual path.</param>
        /// <returns></returns>
        private string RemoteVirtualPathToLocalVirtualPath(string remoteVirtualPath)
        {
            RemoteVirtualPathProvider remoteProvider = Provider as RemoteVirtualPathProvider; 
            if (remoteProvider !=  null)
            {
                return remoteProvider.RemoteVirtualPathToLocalVirtualPath(remoteVirtualPath);
            }
            return remoteVirtualPath;
        }

        /// <summary>
        /// Locals the virtual path to remote virtual path.
        /// </summary>
        /// <param name="localVirtualPath">The local virtual path.</param>
        /// <returns></returns>
        private string LocalVirtualPathToRemoteVirtualPath(string localVirtualPath)
        {
            RemoteVirtualPathProvider remoteProvider = Provider as RemoteVirtualPathProvider;
            if (remoteProvider != null)
            {
                return remoteProvider.LocalVirtualPathToRemoteVirtualPath(localVirtualPath);
            }
            return localVirtualPath;
        }

        #endregion


        #region Properties
        /// <summary>
        /// Gets the dir info.
        /// </summary>
        /// <value>The dir info.</value>
        public RemoteDirectoryInfo DirInfo
        {
            get { return _remoteDirInfo; }
        }

        #endregion
    }
}
